#include "inc\Core\Animation\facialtrack.h"

#include <QMap>
#include "global.h"

RobotFacialTrack::RobotFacialTrack(Robot* robot, QObject *parent) :
    QAbstractAnimation(parent),
    _model(robot)
{
    //Create a start and end key frame
    FacialExpression  blankExpression;
    blankExpression.timestamp = 0;
    blankExpression.filename = "";
    _keyFrames.insert(0, blankExpression);

    blankExpression.timestamp = DEFAULT_DURATION;
    blankExpression.filename = "";
    _keyFrames.insert(DEFAULT_DURATION, blankExpression);
}

void RobotFacialTrack::setRobot(Robot* robot){
    _model = robot;
}

void RobotFacialTrack::updateCurrentTime(int msec){
//    int i, curTimestamp;
//    QList<int> frameTimestamps = _keyFrames.keys();

//    //The facial track is different from the other tracks of the
//    //animation, which can be looked at as having constant change
//    //(or interpolation) between the each point in time.  For example,
//    //the animation doesn't display the pose at a key frame and hold
//    //that pose until the next key frame.  The facial track, however,
//    //does.  For any given point in time along the track, we need
//    //to find out what the previous (in time) facial key frame was
//    //and make sure that it is being displayed.
//    int i;
//    int curTimestamp, curMin = 0;

//    for(i = 0; i < frameTimestamps.count(); i++){
//        curTimestamp = frameTimestamps[i];

//        if(curTimestamp < msec && curTimestamp >= curMin){
//            curMin = curTimestamp;
//        }
//    }

//    //curMin contains the key frame we need to be on
//    if(_curKeyFrame != curMin){
//        qDebug() << "Need to display new facial expression";
//        _curKeyFrame = curMin;

//        //Display new facial expression

//        emit expressionChanged(_curKeyFrame);
//    }

    QMap<int, FacialExpression>::iterator i = _keyFrames.lowerBound(msec);
    if(i != _keyFrames.begin()){
        i--;
    }

    if(i.key() != _curKeyFrame){
        qDebug() << "Need to display new facial expression";
        _curKeyFrame = i.key();

        emit expressionChanged(_curKeyFrame);
    }

}


int RobotFacialTrack::duration() const{
    //The duration will be defined as the timestamp of the last key frame
    return ((_keyFrames.end()) - 1).key();
}


void RobotFacialTrack::setDuration(int msec){
    QList<int> timestamps = _keyFrames.keys();
    FacialExpression removedExpression;

    for(int i = 0; i < timestamps.length(); i++){
        //Delete all of the expressions past the new duration
        if((timestamps[i] > msec) && (i != timestamps.length() - 1)){
            removedExpression = _keyFrames.take(timestamps[i]);
        }
        else if((timestamps[i] > 0) && (i == timestamps.length() - 1)){
            //Maintain the last key frame as the duration
            removedExpression = _keyFrames.take(timestamps[i]);

            _keyFrames.insert(msec, removedExpression);
        }
    }
}

void RobotFacialTrack::setStartExpression(QString filename){
    setExpressionAt(0, filename);
}

void RobotFacialTrack::setEndExpression(QString filename){
    setExpressionAt(duration(), filename);
}

void RobotFacialTrack::setExpressionAt(int msec, QString filename){
    FacialExpression newExpression;
    newExpression.timestamp = msec;
    newExpression.filename = filename;

    _keyFrames.insert(msec, newExpression);
}

void RobotFacialTrack::deleteExpression(int msec){
    _keyFrames.remove(msec);
}

void RobotFacialTrack::moveExpression(int msec, int newMsec){
    if(_keyFrames.contains(msec)){
        FacialExpression removedExpression;
        removedExpression = _keyFrames.take(msec);

        _keyFrames.insert(newMsec, removedExpression);
    }
}

FacialExpressionInfo RobotFacialTrack::expressionAt(int msec) const{
    FacialExpression expression;
    expression.timestamp = -1;
    expression.filename = "";

    expression = _keyFrames.value(msec, expression);

    //It may seem superfluous to be returning a FacialExpressionInfo struct
    //that is exactly the same as a FacialExpression struct, but this is more
    //flexible.  In the future, we may need to have them differ.
    FacialExpressionInfo retValue;
    retValue.filename = expression.filename;
    retValue.timestamp = expression.timestamp;

    return retValue;
}

QList<FacialExpressionInfo> RobotFacialTrack::facialInformation() const{
    QList<FacialExpression> expressions = _keyFrames.values();
    QList<FacialExpressionInfo> retList;
    FacialExpressionInfo curInfo;

    for(int i = 0; i < expressions.length(); i++){
        curInfo.timestamp = expressions[i].timestamp;
        curInfo.filename = expressions[i].filename;

        retList.append(curInfo);
    }

    return retList;
}
